package sole.hawking.image.test;

//Author Simon Horne
//Last modified 16/9/99


/**
 * Image representation consisting of a 2d double array, double values are
 * generated from some convolutions, pixel multiplication (x0.5 etc).
 */
public class Image2DDouble extends Image {
    /**
     * The 2d double array representing pixel grey levels, a value of 100.75 may
     * be used to represent a pixel internally for operators that use double
     * values but when passed to an operator that only uses integer values, the
     * values will be rounded to the nearest integer (101 in this case).
     */
    private double[][] values;

    /**
     * No argument constructor, initialises all variables to 0.
     */
    public Image2DDouble() {
        width = 0;
        height = 0;
        values = new double[0][0];
    }

    /**
     * Constructor that takes a 2d double array and combines this with the width
     * and height to make a new Image2DDouble.
     * 
     * @param width
     *            the width of the Image
     * @param height
     *            the height of the Image
     * @param values
     *            the 2d double array of pixel grey level values
     */
    public Image2DDouble(int width, int height, double[][] values) {
        this.width = width;
        this.height = height;
        this.values = (double[][]) values.clone();
    }

    /**
     * Constructs a new Image2DDouble from a 1d double array.
     * 
     * @param width
     *            the width of the Image
     * @param height
     *            the height of the Image
     * @param values
     *            the 1d double array of pixel grey level values
     */
    public Image2DDouble(int width, int height, double[] values) {
        this.width = width;
        this.height = height;
        this.values = new double[width][height];
        for (int j = 0; j < height; ++j) {
            for (int i = 0; i < width; ++i) {
                this.values[i][j] = values[j * width + i];
            }
        }
    }

    /**
     * Constructs a new Image2DDouble from a 1d int array.
     * 
     * @param width
     *            the width of the Image
     * @param height
     *            the height of the Image
     * @param values
     *            the 1d int array of pixel grey level values
     */
    public Image2DDouble(int width, int height, int[] values) {
        this.width = width;
        this.height = height;
        this.values = new double[width][height];
        for (int j = 0; j < height; ++j) {
            for (int i = 0; i < width; ++i) {
                this.values[i][j] = values[j * width + i];
            }
        }
    }

    /**
     * Converts an existing Image representation to make a new Image2DDouble (an
     * exisiting Image1DDouble is simply cloned).
     * 
     * @param oldImage
     *            the original Image to be converted
     */
    public Image2DDouble(Image oldImage) {
        if (oldImage != null) {
            width = oldImage.getWidth();
            height = oldImage.getHeight();
            if (oldImage instanceof Image2DDouble) {
                values = new double[width][height];
                for (int j = 0; j < height; ++j) {
                    for (int i = 0; i < width; ++i) {
                        values[i][j] = ((Image2DDouble) oldImage).getValues2D()[i][j];
                    }
                }
            } else if (oldImage instanceof Image2DInt) {
                values = new double[width][height];
                for (int j = 0; j < height; ++j) {
                    for (int i = 0; i < width; ++i) {
                        values[i][j] = ((Image2DInt) oldImage).getValues2D()[i][j];
                    }
                }
            } else {
                int[] values1D = (int[]) oldImage.getValues().clone();
                values = new double[width][height];
                for (int j = 0; j < height; ++j) {
                    for (int i = 0; i < width; ++i) {
                        values[i][j] = values1D[j * width + i];
                    }
                }
            }
        }
    }

    /**
     * Returns the pixel values in 1d int form by converting to a 1d array and
     * rounding the double values.
     * 
     * @return the 1d integer array
     */
    public int[] getValues() {
        int[] values1D = new int[width * height];
        for (int j = 0; j < height; ++j) {
            for (int i = 0; i < width; ++i) {
                values1D[j * width + i] = (int) Math.round(values[i][j]);
            }
        }
        return values1D;
    }

    /**
     * Returns the pixel values in 2d double form by returning the internal
     * representation.
     * 
     * @return the 2d double array of pixel values
     */
    public double[][] getValues2D() {
        return values;
    }
}
